/*
 * @Descripttion: 全局异常处理，可在配置文件中设置是否启用
 * @version: 
 * @Author: turingchang
 * @Date: 2020-12-16 11:14:48
 * @LastEditors: turingchang
 * @LastEditTime: 2020-12-16 11:28:21
 */

const {
    dateToTimeStamp
} = require("../common/utils/time");

module.exports = (options) => {
    return async function errorHandler(ctx, next) {
        var start = Date.now();
        ctx.start_time = start;
        try {
            //console.log(0,ctx.status);
            ctx.validate_error = '';
            ctx.errorAndNeedSuccess = false;
            ctx.manual_output = false;
            await next();
            //console.log(1,ctx.status);
            //await dealStatus(ctx, next); 
            await deal(ctx, next, null);
        } catch (err) {
            await deal(ctx, next, err);
        }
    };

    async function deal(ctx, next, err) {
        ctx.end_time = Date.now();
        ctx.interval = ctx.end_time - ctx.start_time;
        var error = '';
        if (!ctx.app.utils.validator.isNull(err)) {
            error = JSON.stringify(err.stack);
        }        
        //error = JSON.stringify(error);
        var res = false;
        //var ss =` ------------------------------------>>>>>>>>> ${ctx.app.name} <<<<<<<<<------------------------------------ \n`;
        var ss = ctx.app.config.console.request.style;
        var s = '';
        if (options.enable === true) {
            //ctx.app.emit('error', error, ctx); //记录任何有异常的记录，输出日志以及输出到控制台            
            switch (ctx.status) {
                case 403:
                    ctx.app.emit('error', error, ctx);
                    ctx.requestLogger.error(ctx.app.enums.response_code_enum.forbid.msg);
                    s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${ctx.app.enums.response_code_enum.forbid.msg} \n` + ss;
                    console.log(s.bgMagenta);
                    return ctx.outError(error, null, ctx.app.enums.response_code_enum.forbid);
                    break;
                case 404:                                   
                    ctx.app.emit('error', error, ctx);
                    //注意，这里服务器报错后仍然为404，而不是500，手动处理
                    if (ctx.app.utils.validator.isNull(err)) {
                        ctx.requestLogger.error(ctx.app.enums.response_code_enum.not_found.msg);
                        //s =ss+`${ctx.request_url} -> `+ctx.app.enums.response_code_enum.not_found.msg+'\n'+ss;
                        s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${ctx.app.enums.response_code_enum.not_found.msg} \n` + ss;
                        console.log(s.bgRed);
                        // return ctx.outError(error, null, ctx.app.enums.response_code_enum.not_found);
                        return ctx.outNotFound(error);
                    } else {
                        ctx.requestLogger.error(JSON.stringify(err.stack));
                        //s =ss+`${ctx.request_url} -> `+err.stack+'\n'+ss;
                        s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${err.stack} \n` + ss;
                        console.log(s.bgRed);
                        return ctx.outError(error, null, ctx.app.enums.response_code_enum.server_error);
                    }                    
                    break;
                case 500:
                    try {
                        if (ctx.app.utils.validator.isNull(error)) {                           
                            if (!ctx.app.utils.validator.isNull(ctx.body.msg)) {
                                error = ctx.body.msg;
                            } else {
                                error = ctx.app.enums.response_code_enum.server_error.msg;
                            }
                        } else {
                            error = ctx.app.enums.response_code_enum.server_error.msg;
                        }
                    } catch {
                        if (ctx.app.utils.validator.isNull(error)) {
                            error = ctx.app.enums.response_code_enum.server_error.msg;
                        }
                    }
                    ctx.app.emit('error', error, ctx);
                    ctx.requestLogger.error(error);
                    s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${error} \n` + ss;
                    console.log(s.bgRed);
                    if (!ctx.app.utils.validator.isNull(err)) {
                        return ctx.outError(error, null, error);
                    }

                    // if (ctx.app.utils.validator.isNull(err)) {
                    //     ctx.requestLogger.error(ctx.app.enums.response_code_enum.server_error.msg);
                    //     //s =ss+`${ctx.request_url} -> `+ctx.app.enums.response_code_enum.server_error.msg+'\n'+ss;
                    //     s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${ctx.app.enums.response_code_enum.server_error.msg} \n` + ss;
                    //     console.log(s.bgRed);
                    // } else {
                    //     ctx.requestLogger.error(JSON.stringify(err.stack));
                    //     //s =ss+`${ctx.request_url} -> `+err.stack+'\n'+ss;
                    //     s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${err.stack} \n` + ss;
                    //     console.log((err.stack).bgRed);
                    // }
                    // return ctx.outError(error, null, ctx.app.enums.response_code_enum.server_error);

                    break;
                default:                    
                    ctx.requestLogger.info();
                    s = ss + `${new Date().toLocaleString()} [${ctx.ip}] [${ctx.method} ${ctx.url}] : ${ctx.response.status}  ${ctx.response.message} \n` + ss;
                    console.log(s.bgGreen);
                    break;
            }

        }

    }

    async function dealStatus(ctx, next, err) {
        var error;
        var res = false;
        if (options.enable === true) {
            switch (ctx.status) {
                case 403:
                    return ctx.outError(error, null, ctx.app.enums.response_code_enum.forbid);
                    break;
                case 404:
                    return ctx.outError(error, null, ctx.app.enums.response_code_enum.not_found);
                    break;
                case 500:
                    return ctx.outError(error, null, ctx.app.enums.response_code_enum.server_error);
                    break;
                default:
                    res = true;
                    break;
            }
        } else {
            res = true;
        }
        return res;

    }


};